package com.project.study.farming.common.utils;

import com.project.study.farming.common.anno.Table;

import java.lang.reflect.Field;
import java.util.*;

/**
 * sql工具类
 *
 * @author mengxj
 * @since 2020-03-12
 */
public class SqlUtil {

    /**
     * 获取实体类insert的sql
     * @param t 实体类实例
     * @param <T> 实体类类型
     * @return 实体类insert的sql
     */
    public static <T> String insert(T t) {
        Class<?> cls = t.getClass();
        Table table = cls.getDeclaredAnnotation(Table.class);
        StringBuilder buffer = new StringBuilder(String.format("insert into %s (", table.value()));
        List<Field> fieldList = getFields(cls);
        StringBuffer cols = new StringBuffer();
        StringBuffer values = new StringBuffer("values (");
        fieldList.forEach(field -> {
            if(!CommonUtil.isMainKey(field)){
                String dataBaseName = CommonUtil.getDataBaseName(field.getName());
                cols.append(String.format("%s,", dataBaseName));
                Object result = CommonUtil.getFieldValue(field, t);
                if (Objects.nonNull(result)) {
                    values.append(String.format("\"%s\",", result));
                } else {
                    values.append(String.format("%s,", result));
                }
            }
        });
        return buffer.append(cols.deleteCharAt(cols.length() - 1).append(") ")).append(values.deleteCharAt(values.length() - 1).append(")")).toString();
    }

    /**
     * 获取实体类根据id修改的sql
     * @param t 实体类实例
     * @param <T> 实体类类型
     * @return 实体类根据id修改的sql
     */
    public static <T> String updateById(T t){
        Class<?> cls = t.getClass();
        Table table = cls.getAnnotation(Table.class);
        StringBuffer buffer = new StringBuffer(String.format("update %s set ", table.value()));
        StringBuffer whereSql = new StringBuffer("where ");
        List<Field> fieldList = getFields(cls);
        fieldList.forEach(field -> {
            Object result = CommonUtil.getFieldValue(field, t);
            String dataBaseName = CommonUtil.getDataBaseName(field.getName());
            if(CommonUtil.isMainKey(field)){
                whereSql.append(String.format("%s = %s", dataBaseName, result));
            }else{
                if("PASSWORD".equalsIgnoreCase(dataBaseName)){
                    buffer.append(String.format("%s = \"%s\",", dataBaseName, result));
                }else if(Objects.nonNull(result)){
                    buffer.append(String.format("%s = '%s',", dataBaseName, result));
                }else{
                    buffer.append(String.format("%s = %s,", dataBaseName, result));
                }
            }
        });
        return buffer.deleteCharAt(buffer.length() - 1).append(" ").append(whereSql).toString();
    }

    /**
     * 无条件查询sql
     * @param cls 实体类类对象
     * @param <T> 实体类类型
     * @return 无条件查询sql
     */
    public static <T> String select(Class<T> cls){
        Table table = cls.getAnnotation(Table.class);
        StringBuffer buffer = new StringBuffer("select ");
        List<Field> fieldList = getFields(cls);
        fieldList.forEach(field -> {
            String fieldName = field.getName();
            buffer.append(String.format("%s %s,", CommonUtil.getDataBaseName(fieldName), fieldName));
        });
        return buffer.deleteCharAt(buffer.length() - 1).append(String.format(" from %s ", table.value())).toString();
    }

    public static <T> String getId(Class<T> cls){
        String tableName = cls.getAnnotation(Table.class).value();
        Field[] fieldList = cls.getDeclaredFields();
        Field field = Arrays.stream(fieldList).filter(CommonUtil :: isMainKey).findFirst().orElse(null);
        assert field != null;
        return String.format("select max(%s) from %s", CommonUtil.getDataBaseName(field.getName()), tableName);
    }

    /**
     * 获取所有属性
     * @param cls 类对象
     * @return 所有属性
     */
    private static List<Field> getFields(Class<?> cls){
        List<Field> fieldList = new ArrayList<>();
        Class<?> parentClass = cls.getSuperclass();
        Collections.addAll(fieldList, cls.getDeclaredFields());
        while (!Objects.equals(parentClass, Object.class)){
            Collections.addAll(fieldList, parentClass.getDeclaredFields());
            parentClass = parentClass.getSuperclass();
        }
        return fieldList;
    }
}
